﻿package bdz.common.managers
{
	import bdz.common.events.GenericEvent;
	import bdz.common.utils.GlobalRender;
	import flash.media.SoundTransform;
	import flash.net.LocalConnection;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.ProgressEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundLoaderContext;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.net.URLRequest;
	import flash.utils.*;
	/**
	 * ...
	 * @author ...
	 */
	public class AudioControlManager extends EventDispatcher 
	{
		private var _source:String;
		public var _refreshRate:Number = 30;
		private var _sound:Sound;
		private var _ureq:URLRequest;
		private var _context:SoundLoaderContext;
		private var _autoPlay:Boolean = false;
		private var _inter:Number;
		private var _channel:SoundChannel;
		private var _pausepos:Number = 0;
		private var _onflv:Boolean = false;
		private var _ns:NetStream;
		private var _nc:NetConnection;
		private var _streaminterval:Number;
		private var _nsduration:Number;
		private var _completed:Boolean = false;
		public var loadOffset:Number = 0;
		private var _defvolume:Number = 1;
		function AudioControlManager() {
			
			
		}
		protected function initializeComponent():void {
			try {
				_sound.close();
				
			}catch (e:Error) {
				
			}
			try{
				_ns.close();
				_nc.close();
			}catch(e:Error){
				
			}
			if(_onflv){
				handleFLV();
				return;
			}
			_context = new SoundLoaderContext();
			_sound = new Sound(_ureq, _context);
			
			_sound.addEventListener(Event.COMPLETE, soundLoadComplete);
			_sound.addEventListener(ProgressEvent.PROGRESS, soundLoadProgress);
			if(_autoPlay){
				play();
			}
			
		}
		protected function onFLVMeta(item:Object):void{
			_nsduration = item.duration * 1000;
			var pct:Number = _ns.bytesLoaded / _ns.bytesTotal;
			dispatchEvent(new GenericEvent(GenericEvent.LOAD_PROGRESS, { percentTotal:pct, length:_nsduration, loaded:_ns.bytesLoaded, total:_ns.bytesTotal} ));
		}
		protected function handleFLV():void{
			_nc = new NetConnection();
			_nc.connect(null);
			_ns = new NetStream(_nc);
			_ns.client = {};
			_ns.client.onMetaData = onFLVMeta;
			_ns.client.onPlayStatus = onFLVPlayComplete;
			_ns.play(_source);
			_ns.pause();
			_streaminterval = setInterval(preloadStream, 100);
			
		}
		protected function preloadStream():void {
			var pct:Number = _ns.bytesLoaded / _ns.bytesTotal;
			pct += loadOffset;
			
			if(pct >= 1){
				dispatchEvent(new GenericEvent(GenericEvent.COMPLETE));
				clearInterval(_streaminterval);
			}else{
				dispatchEvent(new GenericEvent(GenericEvent.LOAD_PROGRESS, { percentTotal:pct, length:_nsduration, loaded:_ns.bytesLoaded, total:_ns.bytesTotal} ));
			}
		}
		protected function playProgress():void {
			var pct:Number;
			
			if(_onflv){
				pct = _ns.time / _nsduration;
				dispatchEvent(new GenericEvent(GenericEvent.PROGRESS, { percentTotal:pct, position:_ns.time*1000, length:_nsduration } ));
			}else{
				pct = _channel.position / _sound.length;
				dispatchEvent(new GenericEvent(GenericEvent.PROGRESS, { percentTotal:pct, position:_channel.position, length:_sound.length } ));
			}
			
			
			
		}
		protected function onFLVPlayComplete(evt:Object):void {
			if (evt.info.code == "NetStream.Play.Complete") {
				dispatchEvent(new GenericEvent(GenericEvent.PROGRESS_COMPLETE));
			}
		}
		protected function onAudioPlayComplete(evt:Event):void {
			clearInterval(_inter);
			dispatchEvent(new GenericEvent(GenericEvent.PROGRESS_COMPLETE));
		}
		protected function soundLoadProgress(evt:ProgressEvent):void {
			if(!_completed){
			var pct:Number = (evt.bytesLoaded / evt.bytesTotal) + loadOffset;
				if (pct >= 1) {
					_completed = true;
					dispatchEvent(new GenericEvent(GenericEvent.COMPLETE));
				}else{
					dispatchEvent(new GenericEvent(GenericEvent.LOAD_PROGRESS, { loaded:evt.bytesLoaded, total:evt.bytesTotal, percentTotal:evt.bytesLoaded / evt.bytesTotal, length:_sound.length } ));
				}
			}
		}
		protected function soundLoadComplete(evt:Event):void {
			if(!_completed){
				dispatchEvent(new GenericEvent(GenericEvent.COMPLETE));
				_completed = true;
			}
		}
		protected function convertToTime(n:Number):Number {
			if(_onflv){
				return (n*_nsduration)/100;	
			}
			return (n*_sound.length)/100;
		}
		public function clear():void { 
			clearInterval(_inter);
			try {
				_channel.stop();
			}catch(e:Error){}
			try {
				_sound.removeEventListener(Event.COMPLETE, soundLoadComplete);
				_sound.removeEventListener(ProgressEvent.PROGRESS, soundLoadProgress);
				_sound.close();
			}catch (e:Error) {}
			try {
				_nc.close();
				_ns.close();
			}catch (e:Error) { }
			_sound = null;
			_channel = null;
			var lc:LocalConnection = new LocalConnection();
			try {
				lc.connect("bogus");
				lc.connect("bogus");	
			}catch (e:Error){}
			trace("audio cleared");
		
			
		}
		public function play():void {
			if(_onflv){
				_ns.seek(_pausepos);
				_ns.resume()
			}else {
				try {
					_channel.removeEventListener(Event.SOUND_COMPLETE, onAudioPlayComplete);
				}catch (e:Error) { };
				var _trans:SoundTransform = new SoundTransform(_defvolume);
				_channel = _sound.play(_pausepos, 0, _trans);
				_channel.addEventListener(Event.SOUND_COMPLETE, onAudioPlayComplete);
			}
			clearInterval(_inter);
			_inter = setInterval(playProgress, _refreshRate);
		}
		public function pause():void{
			if(_onflv){
				_pausepos = _ns.time;
				_ns.pause();
				
			}else{
				_pausepos = _channel.position;
				_channel.stop();
			}
			clearInterval(_inter);
		}
		public function abort():void {
			try {
				_channel.stop();
				_sound.close();
			}catch (e:Error) { };
		}
		public function set percentPosition(n:Number):void {
			var newtime:Number = convertToTime(n*100);
			if(_onflv){
				_ns.seek(newtime/1000);
					
			}else{
				_channel.stop();
				_channel = _sound.play(newtime, 0);
			}
		}
		public function set volume(n:Number):void {
			_defvolume = n;
			var _trans:SoundTransform = new SoundTransform(_defvolume); 
			try{
				_channel.soundTransform = _trans;
			}catch(e:Error){}
		}
		public function get baseChannel():SoundChannel {
			return _channel;
		}
		public function set autoPlay(b:Boolean):void {
			_autoPlay = b;
		}
		public function get autoPlay():Boolean {
			return _autoPlay;
		}
		public function set source(str:String):void {
			_onflv = (str.indexOf(".flv") != -1);
			_source = str;
			_ureq = new URLRequest(_source);
			_completed = false;
			initializeComponent();
		}
		public function get source():String {
			return _source;
		}
		//READ ONLY
		public function get duration():Number {
			if(_onflv){
				return _nsduration;
			}
			return _sound.length;
		}
		public function get position():Number {
			if(_onflv){
				return _ns.time * 1000;
			}
			try{
				return _channel.position;
			}catch(e:Error){
				
			}
			return 0;
		}
		public function shush():void {
			
		}
		public function set refreshRate(n:Number):void {
			_refreshRate = n;
		}
		public function get refreshRate():Number {
			return _refreshRate;
		}
		
	}
	
}